package com.hyzh.latte.sandtable.service;

import cn.hutool.core.util.StrUtil;
import com.hyzh.latte.sandtable.mapper.GeoQueryMapper;
import com.hyzh.latte.sandtable.pojo.GeoQuery.IndexAndPoint;
import com.hyzh.latte.sandtable.pojo.Graph.PointNode;
import com.hyzh.latte.sandtable.pojo.Graph.TempConnect;
import com.hyzh.latte.sandtable.pojo.PointData;
import com.hyzh.latte.sandtable.pojo.Vector_Line_2D;
import com.hyzh.latte.sandtable.pojo.Vector_Point_2D;
import com.hyzh.latte.sandtable.utils.VectorUtils;
import com.hyzh.latte.vehicle.dmo.ParkRoadEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
@AllArgsConstructor
public class GeoQueryService {
    private final GeoQueryMapper geoQueryMapper;
    private final GraphService graphService;

    public List<Vector_Point_2D> findShortestRoad(Vector_Point_2D startPoint, Vector_Point_2D endPoint, String area) {
        ArrayList<Vector_Point_2D> resultPoints = new ArrayList<>();
        //寻找距离点最近的线段的信息

        //首先查询表中是否存在这个点
        Integer startPointIndex = geoQueryMapper.findClosestPoint(startPoint, area + "_node");
        Integer endPointIndex = geoQueryMapper.findClosestPoint(endPoint, area + "_node");
        if (startPointIndex != null && endPointIndex != null) {
            ArrayList<PointNode> resultPointNode = graphService.findShortestPathByIndex(startPointIndex, endPointIndex, area + "_graph");
            resultPointNode.forEach((element) -> {
                Vector_Point_2D tempPoint = new Vector_Point_2D(element.getPoint().getX(), element.getPoint().getY());
                resultPoints.add(tempPoint);
            });
        } else {
            //对于出发点
            IndexAndPoint startClosestLineToPoint = geoQueryMapper.findClosestLineToPoint(startPoint, area + "_line");
            Vector_Point_2D startMidPoint = VectorUtils.stringToVectorPoint2D(startClosestLineToPoint.getPoint0());
            Vector_Line_2D startLine = geoQueryMapper.selectLineByIndex(startClosestLineToPoint.getIndex(), area + "_line");
            Vector_Point_2D startNode0 = new Vector_Point_2D(startLine.getStartX() , startLine.getStartY());
            Vector_Point_2D startNode1 = new Vector_Point_2D(startLine.getEndX(), startLine.getEndY());
            Integer startIndex0 = geoQueryMapper.selectNodeIndexByCoords(startNode0, area + "_node");
            Integer startIndex1 = geoQueryMapper.selectNodeIndexByCoords(startNode1, area + "_node");
            double startDistance0 = geoQueryMapper.getDistanceBetweenTwoPoints(startMidPoint, startNode0);
            double startDistance1 = geoQueryMapper.getDistanceBetweenTwoPoints(startMidPoint, startNode1);
            TempConnect startTempConnect0 = new TempConnect(startMidPoint, startIndex0, startDistance0);
            TempConnect startTempConnect1 = new TempConnect(startMidPoint, startIndex1, startDistance1);

            //对于结束点
            IndexAndPoint endClosestLineToPoint = geoQueryMapper.findClosestLineToPoint(endPoint, area + "_line");
            Vector_Point_2D endMidPoint = VectorUtils.stringToVectorPoint2D(endClosestLineToPoint.getPoint0());
            Vector_Line_2D endLine = geoQueryMapper.selectLineByIndex(endClosestLineToPoint.getIndex(), area + "_line");
            Vector_Point_2D endNode0 = new Vector_Point_2D(endLine.getStartX(), endLine.getStartY());
            Vector_Point_2D endNode1 = new Vector_Point_2D(endLine.getEndX(), endLine.getEndY());
            Integer endIndex0 = geoQueryMapper.selectNodeIndexByCoords(endNode0, area + "_node");
            Integer endIndex1 = geoQueryMapper.selectNodeIndexByCoords(endNode1, area + "_node");
            double endDistance0 = geoQueryMapper.getDistanceBetweenTwoPoints(endMidPoint, endNode0);
            double endDistance1 = geoQueryMapper.getDistanceBetweenTwoPoints(endMidPoint, endNode1);
            TempConnect endTempConnect0 = new TempConnect(endMidPoint, endIndex0, endDistance0);
            TempConnect endTempConnect1 = new TempConnect(endMidPoint, endIndex1, endDistance1);
            if (startLine == endLine) {
                resultPoints.add(startMidPoint);
                resultPoints.add(endMidPoint);
            } else {
                ArrayList<PointNode> resultPointNode = graphService.findShortestPathBetweenPoints(startTempConnect0, startTempConnect1, endTempConnect0, endTempConnect1, area + "_graph");
                resultPointNode.forEach((element) -> {
                    Vector_Point_2D tempPoint = new Vector_Point_2D(element.getPoint().getX(), element.getPoint().getY());
                    resultPoints.add(tempPoint);
                });
            }
        }
        return resultPoints;
    }

    public List<PointData> pointFitToRoads(List<PointData> pointDataList, String park) {
//        String area = "gaoxin".equals(park) ? park + "_roads_test3" : park +"_roads";
        String area = Optional.ofNullable(ParkRoadEnum.ofCode(park)).map(ParkRoadEnum::fit).orElse(null);
        if (StrUtil.isEmpty(area)){
            log.error("area is null park ： {}", park);
            return null;
        }

        for (int i = 0; i < pointDataList.size(); i++) {
            Vector_Point_2D point = new Vector_Point_2D(pointDataList.get(i).getLon(), pointDataList.get(i).getLat());
            IndexAndPoint strMidPoint = geoQueryMapper.findClosestLineToPoint(point, area + "_line");
            Vector_Point_2D midPoint = VectorUtils.stringToVectorPoint2D(strMidPoint.getPoint0());
            PointData resultPointDate = new PointData(midPoint.getX(), midPoint.getY(), pointDataList.get(i).getHeight(), pointDataList.get(i).getPointNo(), strMidPoint.getIndex());
            pointDataList.set(i, resultPointDate);
        }
        return pointDataList;
    }
}
